/*
 * @Author: complex 1944755442@qq.com
 * @Date: 2024-03-11 17:39:12
 * @LastEditors: complex 1944755442@qq.com
 * @LastEditTime: 2024-03-11 18:21:09
 * @FilePath: /28_socket/learn_libevent/bufferlibevent/test.c
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */


//类C的C++编译选项：g++ main.cpp data_process.cpp comm.cpp map_build.cpp -o test -levent -lpthread
//面向对象C++编译选项  g++ main.cpp data_process.cpp comm.cpp map_build.cpp food_define.cpp snake_define.cpp -o test -levent -lpthread
//1. 创建套接字，接受多个客户端的连接
//2. 接收客户端发过来的数据
//3. 对数据进行处理
//4. 将数据封装好，发给客户端
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>
#include <ctype.h>
#include <list>

//多线程
#include <pthread.h>

//User's include
#include "main.h"
#include "food_define.h"
#include "snake_define.h"
#include "data_process.h"
#include "comm.h"

GameStat g_gamestat;
//PicCode map[80][80];
Map global_map;
Map global_map_copy(global_map);

std::list<FoodNode> food_list;
std::list<Snake> snake_list;

void game_init()
{
    g_gamestat = GAME_MENU;

    //初始化地图（已由C++构造函数完成）
#if 0
    //随机生成若干食物
    for(int i=0; i<20; i++)
    {
        create_a_food();
    }
#endif 
    //初始化生成一个食物，位置在指定位置
    FoodNode banana(60,20);
    food_list.push_back(banana);
    
    banana.set_pos(30,21);
    food_list.push_back(banana);

    int gap = 5;
    for(int i=0; i<10; i++)
    {
        //banana.set_pos(10+gap*i,10);
        //food_list.push_back(banana);
        banana.create_a_valid_food();
    }
}

int main()
{
    // 地址结构体
    struct sockaddr_in serve_addr;
    serve_addr.sin_family = AF_INET;
    serve_addr.sin_port = htons(SERVER_PORT);
    serve_addr.sin_addr.s_addr = htonl(INADDR_ANY);

    // 1. 创建底座
    struct event_base *base = event_base_new();
    // 2. 创建listener监听对象,(监听是否有客户端连接)
    //这里选项为 LEV_OPT_REUSEABLE 相当于普通 event 里面的 EV_PERSIST
    struct evconnlistener *listener;
    listener = evconnlistener_new_bind(base, listener_cb, base,
                                       LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
                                       -1, (struct sockaddr *)&serve_addr, sizeof(serve_addr));
    //此函数相当于 socket()+bind()+listen()+accpet()四个函数
    //创建两个辅助线程：一个用于向客户端定时发送 map ；另外一个处理 snake_list 和 map 
    game_init();
    pthread_t send_map_tid = 0;
    pthread_t snake_move_tid = 0;
    pthread_create(&send_map_tid, NULL,send_map,NULL);
    pthread_create(&snake_move_tid, NULL, snake_move,NULL);

    // 3. 启动循环监听
    printf("Start dispatch..............\n");
    event_base_dispatch(base);
	 
    // 4. 释放
    event_base_free(base);         // 底座
    evconnlistener_free(listener); // 监听器

    return 0;
}

